想知道nm命令的实现原理吗 您所在的位置:网站首页 nm 无符号 想知道nm命令的实现原理吗

想知道nm命令的实现原理吗

2024-07-02 13:23| 来源: 网络整理| 查看: 265

在AIX及其他unix/linux平台上,我们可以使用nm, objdump和readelf来分析ELF文件的符号表。具体使用方式是: nm objfile objdump -x objfile (或其他选项) readelf -a objfile

但我们有时候需要在程序中来分析某个ELF文件(比如当前进程)的符号表,进行处理。这里针对AIX平台介绍附件中的代码所使用的方法来实现该功能。 附件中的C++代码巧妙利用了AIX提供的系统调用来读出ELF文件的符号表,它以面向对象的方式提供了如下接口:

class XCOFFParser; //void * is SCNHDR * for 32 bit and SCNHDR_64 for 64 bit. //Return 0, contiue. Return 1: break the current parse. typedef int (*SectionCallback)(void *param, XCOFFParser *parser, int iIndex, void *secHeader); //void * is SYMENT * for 32 bit and SYMENT_64 for 64 bit. //Return 0, contiue. Return 1: break the current parse. typedef int (*SymbolCallback)(void *param, XCOFFParser *parser, int iIndex, char *symName, void *symEntry); enum XCOFF_SECTION{SECTION_TEXT=0, SECTION_DATA, SECTION_BSS, SECTION_DEBUG, SECTION_LOADER}; struct SectionInfo {     XCOFF_SECTION sectionType;     int sectionNum;     char sectionName[MAX_SECTION_NAME_LENGTH]; }; class XCOFFParser { public:     XCOFFParser(char *fileName)     {         strcpy(m_strFileName, fileName);         m_ldPointer = NULL;         m_bIs64 = 0;         m_lSections = m_lSymbols = 0;         memset(m_sections, -1, sizeof(m_sections));     }     virtual ~XCOFFParser();               int InitParser();          int ParseSections(SectionCallback pfnCallback, void *param, int iIncludeDep=0);     int ParseSymbols(SymbolCallback pfnCallback, void *param, int iIncludeDep=0);     int DeinitParser();     int Is64Bit()     {         return m_bIs64;     }          char *GetFileName(char *buf) const     {         strcpy(buf, m_strFileName);         return buf;     }     long GetSectionsNumber() const     {         return m_lSections;     }     long GetSymbolsNumber() const     {         return m_lSymbols;     }     int IsDebugSymbol(void *symEntry)     {         if(m_bIs64)         {             return ((SYMENT_64 *)symEntry)->n_scnum == N_DEBUG;         }         return ((SYMENT *)symEntry)->n_scnum == N_DEBUG;     }     int IsABSSymbol(void *symEntry)     {         if(m_bIs64)         {             return ((SYMENT_64 *)symEntry)->n_scnum == N_ABS;         }         return ((SYMENT *)symEntry)->n_scnum == N_ABS;     }     int IsUndefSymbol(void *symEntry)     {         if(m_bIs64)         {             return ((SYMENT_64 *)symEntry)->n_scnum == N_UNDEF;         }         return ((SYMENT *)symEntry)->n_scnum == N_UNDEF;     }     int IsDefinedSymbol(void *symEntry)     {         int iInMem = (m_bIs64? ((SYMENT_64 *)symEntry)->n_sclass C_BLOCK:((SYMENT *)symEntry)->n_sclass C_BLOCK);         return !IsDebugSymbol(symEntry) && !IsABSSymbol(symEntry)                 && !IsUndefSymbol(symEntry) && iInMem;     }     int IsTextSymbol(void *symEntry)//Functions' symbol     {         if(m_bIs64)         {             return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_TEXT].sectionNum;         }         return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_TEXT].sectionNum;     }        int IsDataSymbol(void *symEntry)//data symbol     {         if(m_bIs64)         {             return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_DATA].sectionNum;         }         return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_DATA].sectionNum;     }     int IsBssSymbol(void *symEntry)     {         if(m_bIs64)         {             return ((SYMENT_64 *)symEntry)->n_scnum == m_sections[SECTION_BSS].sectionNum;         }         return ((SYMENT *)symEntry)->n_scnum == m_sections[SECTION_BSS].sectionNum;     } /*     int IsDebugSymbol(SYMENT *symEntry)     {         return symEntry->n_scnum == m_sections[SECTION_DEBUG].sectionNum;     } */      protected:     char m_strFileName[MAX_PATH_LEN];         LDFILE* m_ldPointer;     int m_bIs64;     long m_lSections, m_lSymbols;     SectionInfo m_sections[MAX_SECTIONS]; }; 示例程序: #include #include "xcoff_parser.h" static int SymbolReadDefinedFuncs(void *param, XCOFFParser *parser, int iIndex, char *symName, void *symEntry) {     //printf("In callback\n");     if(strlen(symName) > 0 && parser->IsDefinedSymbol(symEntry) && parser->IsTextSymbol(symEntry))     {         //It's a function definition, let's store it into the map         printf("Defined function name:%s, address:%p\n", symName,                             parser->Is64Bit()? ((SYMENT_64 *)symEntry)->n_value: ((SYMENT *)symEntry)->n_value);              }     return 0; } int main(int argc, char *argv[]) {      XCOFFParser parser(buf);      int ret = parser.InitParser();      if(ret != ERROR_XCOFF_SUCCESS)      {          printf("XCOFFParser::InitParser failed:%d.\n", ret);         return ret;      }      ret = parser.ParseSections(NULL, NULL);      if(ret != ERROR_XCOFF_SUCCESS)      {          printf("XCOFFParser::ParseSections failed:%d.\n", ret);         return ret;      }      ret = parser.ParseSymbols(SymbolReadDefinedFuncs, NULL);      if(ret != ERROR_XCOFF_SUCCESS)      {          printf("XCOFFParser::ParseSymbols failed:%d.\n", ret);         return ret;      }      return 0; }

xcoff_parser中所使用到的主要系统调用:

LDFILE *ldopen( char *, LDFILE * ); int ldfhread( LDFILE *, void * ); int ldshread( LDFILE *, unsigned short, void * ); int ldtbread( LDFILE *, int, void * ); int ldclose( LDFILE * );  xcoff_parser.zip  

当看完下面这本书之后,你会发现你也可以实现这个功能: 《返璞归真--UNIX技术内幕》



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有